import time
from hytest import *
from selenium import webdriver
from selenium.webdriver import ActionChains

def driver_get(brower_type):
    driver = getattr(webdriver,brower_type)()
    return driver

class BasePage:
    ipaddr = '***.***.***.***'
    m_url = 'http://ipaddr/mgr/login/login.html'.replace('ipaddr',ipaddr)
    t_url = 'http://ipaddr/teacher/login/login.html'.replace('ipaddr',ipaddr)
    s_url = 'http://ipaddr/student/login/login.html'.replace('ipaddr',ipaddr)

    def __init__(self,driver):
        self.driver = driver
        self.driver.implicitly_wait(5)

    def open(self,url):
        self.driver.get(url)

    def locate(self,loc):
        return self.driver.find_element(*loc)

    def locates(self,loc):
        return self.driver.find_elements(*loc)

    def locates_to_locate(self,loc,index):
        return self.locates(loc)[index-1]

    def input(self,loc,txt):
        self.locate(loc).send_keys(txt)

    def click(self,loc,index=None,flag_all=False):
        if flag_all:
            for i in self.locates(loc):
                i.click()
                time.sleep(0.5)
        elif index:
            self.locates_to_locate(loc,index).click()
        else:
            self.locate(loc).click()
        time.sleep(0.3)

    def clear(self,loc):
        self.locate(loc).clear()

    def get_txt(self,loc):
        time.sleep(0.2)         #不可删除强制等待
        return self.locate(loc).text

    def get_txts(self,loc):
        time.sleep(0.2)         #不可删除强制等待
        element_list = self.locates(loc)
        ret_list = []
        for i in element_list:
            ret_list.append(i.text)
        return ret_list

    def get_txt_or_txts(self,loc):
        time.sleep(0.2)         #不可删除强制等待
        element_list = self.locates(loc)
        if len(element_list) == 1:
            return element_list[0].text
        else:
            ret_list = []
            for i in element_list:
                ret_list.append(i.text)
            return ret_list

    def move_to(self,loc):
        ActionChains(self.driver).move_to_element(self.locate(loc)).perform()

    def jump_iframe(self,iframe_name):
        self.driver.switch_to.frame(iframe_name)
        time.sleep(0.5)

    def leave_iframe(self):
        self.driver.switch_to.default_content()

    # 层级loc编辑：层级value组合
    #return格式不符合返回规则，不可直接调用
    def set_floor_loc_text(self,loc_value_input,index_dict):
        if isinstance(loc_value_input,list):
            text_count = len(index_dict)
            loc_text = ''
            for t in loc_value_input[:text_count]:
                loc_text += t
        else:
            loc_text = loc_value_input
        return loc_text

    #层级loc编辑：index
    #return格式不符合返回规则，不可直接调用
    def set_floor_loc_index(self,loc_value,index_dict):
        for k,v in index_dict.items():
            loc_value = loc_value.replace(k,str(v))
        return loc_value

    #层级目录点击
    #loc_text_list: 包含树各层级的 loc_vlaue 值
    #**kwargs 层级与索引
        #层级 ：index + 层级数  组成的字符串
        #索引 ：层级之下的 整数索引
    def click_floor(self,loc_method,loc_value_input,**kwargs):
        no_index_loc_text = self.set_floor_loc_text(loc_value_input,kwargs)
        loc_text = self.set_floor_loc_index(no_index_loc_text,kwargs)
        loc = (loc_method,loc_text)
        try:
            self.click(loc)
            time.sleep(0.5)     #不可删除强制等待
            return {'ret':0}
        except:
            return {'ret':1,
                    'msg':'floor点击失败'}

    def click_floors(self,floor_list):
        for dict in floor_list:
            ret = self.click_floor(**dict)
            if ret['ret'] != 0:
                break
        return ret


    def get_txt_floor(self,loc_method,loc_value_input,**kwargs):
        no_index_loc_text = self.set_floor_loc_text(loc_value_input, kwargs)
        loc_text = self.set_floor_loc_index(no_index_loc_text, kwargs)
        loc = (loc_method, loc_text)
        try:
            ret_text = self.get_txt(loc)
            return {'ret':0,
                    'msg':ret_text}
        except:
            return {'ret': 1,
                    'msg': 'floor text获取失败'}


    #根据按键名称 button 进行点击操作，并且不存在等情况下关闭提示窗
    #前提：类中定义button_dict，存放能够点击的按钮
        #button: 要操作的按键名
        #button_dict: 按键名 与 loc组成的键值对
        #loc_pop: 无数据等状态下跳出弹窗的loc
    def click_button(self,button):
        if button not in self.button_dict:
            return {'ret': 1,
                    'msg': r'按钮 {button} 不在可操作范围内'}
        else:
            self.click(self.button_dict[button])
            # time.sleep(0.5)    #不可删除强制等待

            self.driver.implicitly_wait(0.5)
            try:
                self.click(self.loc_pop)
            except:
                pass
            self.driver.implicitly_wait(5)
            return {'ret': 0}

    #可设定点击多按钮
        #button_list: 储存所有按键名的list
    def click_buttons(self,button_list):
        defeat_button_list = []
        for button in button_list:
            ret = self.click_button(button)
            if ret['ret'] != 0:
                defeat_button_list.append(ret['msg'])
        if defeat_button_list:
            return {'ret': 1,
                    'msg': f'下列按钮操作失败 {defeat_button_list}'}
        else:
            return {'ret': 0}

    step = STEP
    info = INFO
    check_point = CHECK_POINT

    def workflow(self,flow_dict):
        obj = flow_dict.pop('obj')
        for f,v in flow_dict.items():
            if v is not None:
                if isinstance(v,dict):
                    ret = getattr(obj,f)(**v)
                elif isinstance(v,list):
                    ret = getattr(obj,f)(*v)
                else:
                    ret = getattr(obj,f)(v)
            else:
                ret = getattr(obj,f)()
            if isinstance(ret,dict):
                if ret['ret']:
                    if ret['ret'] != 0:
                        return ret
        return ret

    def alert_ok(self):
        self.driver.switch_to.alert.accept()

    def alert_text(self):
        return self.driver.switch_to.alert.text

    def alert_dismiss(self):
        self.driver.switch_to.alert.dismiss()

    def alert_input(self,input_txt):
        self.driver.switch_to.alert.send_keys(input_txt)

    def jump_window(self,window_name):
        main_window = self.driver.current_window_handle
        for handle in self.driver.window_handles:
            self.driver.switch_to.window(handle)
            if window_name in self.driver.title:
                break
        return main_window

    def return_main_window(self,main_window):
        self.driver.switch_to.window(main_window)

    def close(self):
        self.driver.close()

    def get_attribute(self,loc,attribute_key):
        return self.locate(loc).get_attribute(attribute_key)

    def get_attribute_innerText(self,loc):
        return self.locate(loc).get_attribute('innerText')

    def get_attribute_textContent(self,loc):
        return self.locate(loc).get_attribute('textContent')

    def screenshot(self):
        SELENIUM_LOG_SCREEN(self.driver, width='70%')

    def time_sleep(self,s):
        time.sleep(s)